package com.yh.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @ClassName NIOClient
 * @Description TODO
 * @Author 0715-YuHao
 * @Date 2020/12/17 15:51
 */
public class NIOClient {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Worker().start();
        }
    }

    private static class Worker extends Thread {
        @Override
        public void run() {
            SocketChannel channel = null;
            Selector selector = null;
            try {
                // SocketChannel，一看底层就是封装了一个Socket
                channel = SocketChannel.open(); // SocketChannel是连接到底层的Socket网络
                // 数据通道就是负责基于网络读写数据的
                channel.configureBlocking(false);
                channel.connect(new InetSocketAddress("localhost", 9000));
                selector = Selector.open();
                channel.register(selector, SelectionKey.OP_CONNECT);
                while (true) {
                    selector.select();
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (key.isConnectable()) {
                            if (channel.isConnectionPending()) {
                                channel.finishConnect();
                                ByteBuffer buffer = ByteBuffer.allocate(1024);
                                buffer.put("你好".getBytes());
                                buffer.flip();
                                channel.write(buffer);
                            }
                            channel.register(selector, SelectionKey.OP_READ);
                        }else if (key.isReadable()) {
                            channel = (SocketChannel) key.channel();
                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                            int len = channel.read(buffer);
                            if (len > 0) {
                                System.out.println("[" + Thread.currentThread().getName() + "]收到响应：" +
                                        new String(buffer.array(), 0, len));
                                Thread.sleep(3000);
                                channel.register(selector, SelectionKey.OP_WRITE);
                            }
                        }else if (key.isWritable()) {
                             ByteBuffer buffer = ByteBuffer.allocate(1024);
                            buffer.put("你好".getBytes());
                            buffer.flip();
                            channel = (SocketChannel) key.channel();
                            channel.write(buffer);
                            channel.register(selector, SelectionKey.OP_READ);
                        }
                    }
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }finally {
                if (channel != null) {
                    try {
                        channel.close();
                    } catch (IOException exception) {
                        exception.printStackTrace();
                    }
                }
                if   (selector != null) {
                    try {
                        selector.close();
                    } catch (IOException exception) {
                        exception.printStackTrace();
                    }
                }
            }
        }
    }
}
